package org.example.domain.award.service;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.example.domain.award.event.SendAwardMessageEvent;
import org.example.domain.award.model.aggregate.UserAwardRecordAggregate;
import org.example.domain.award.model.entity.DistributeAwardEntity;
import org.example.domain.award.model.entity.UserAwardRecordEntity;
import org.example.domain.award.repository.IAwardRepository;
import org.example.domain.award.service.distribute.IDistributeAward;
import org.example.domain.task.model.entity.TaskEntity;
import org.example.domain.task.model.valobj.TaskStateVO;
import org.example.types.event.BaseEvent;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Map;

@Slf4j
@Service
public class AwardService implements IAwardService{

    @Resource
    private IAwardRepository awardRepository;

    //获取Mq辅助对象,用于生成标准MQ消息及获取topic
    @Resource
    private SendAwardMessageEvent sendAwardMessageEvent;


    @Resource
    private Map<String,IDistributeAward> beanMap;

    /**
     * 保存中奖记录,发送中奖消息来异步发奖
     * @param userAwardRecordEntity 中奖记录实体
     */
    @Override
    public void saveUserAwardRecord(UserAwardRecordEntity userAwardRecordEntity) {

        //构建消息的Data
        SendAwardMessageEvent.SendAwardMessage sendAwardMessage = SendAwardMessageEvent.SendAwardMessage.builder()
                .awardId(userAwardRecordEntity.getAwardId())
                .awardTitle(userAwardRecordEntity.getAwardTitle())
                .userId( userAwardRecordEntity.getUserId())
                .orderId(userAwardRecordEntity.getOrderId())
                .config(userAwardRecordEntity.getConfig())
                .build();
        //构建整个消息
        BaseEvent.EventMessage<SendAwardMessageEvent.SendAwardMessage> sendAwardMessageEventMessage = sendAwardMessageEvent.buildEventMessage(sendAwardMessage);

        //构建任务实体,将date弄为JSON格式
        TaskEntity taskEntity = TaskEntity.builder()
                .topic(sendAwardMessageEvent.topic())
                .messageId(sendAwardMessageEventMessage.getId())
                .message(JSON.toJSONString(sendAwardMessageEventMessage))
                .state(TaskStateVO.create)
                .userId(userAwardRecordEntity.getUserId())
                .build();

        //构建任务实体和中奖记录聚合类型
        UserAwardRecordAggregate userAwardRecordAggregate = UserAwardRecordAggregate.builder()
                .taskEntity(taskEntity)
                .userAwardRecordEntity(userAwardRecordEntity)
                .build();


        awardRepository.saveUserAwardRecord(userAwardRecordAggregate);

    }

    /**
     * 消费者接受发奖消息的回调函数
     * 使用依赖倒置原则,根据奖品类型得到对应的奖品发奖实现类,再进行发奖
     *
     * 发奖有不同的奖品,意味着要根据不同奖品类型进行发奖,常规的做法是根据奖品类型编写if-else
     * 这里使用策略设计模式,将不同类型的奖品发奖编写成方法,使用通统一抽象接口,不同实现类来代表不同发奖方式
     *
     * @param distributeAwardEntity 发奖奖品实体
     */
    @Override
    public void distributeAward(DistributeAwardEntity distributeAwardEntity) {
        String awardKey = awardRepository.queryAwardKeyByAwardId(distributeAwardEntity.getAwardId());
        if (StringUtils.isBlank(awardKey)){
            log.error("分发奖品，奖品ID不存在。awardKey:{}", awardKey);
            return;
        }


        IDistributeAward distributeAward = beanMap.get(awardKey);
        if (null == distributeAward) {
            log.error("分发奖品，对应的服务不存在.awardKey:{}", awardKey);
            throw new RuntimeException("分发奖品，奖品" + awardKey + "对应的服务不存在");
        }
        distributeAward.giveOutPrizes(distributeAwardEntity);

    }
}
